//////////////////////////////////////////////////////////////////////////////////////////////////////
// 项目名   : Container
// 文件名   : TestMultiSet.h
// 作者     : Aiye
// 日期     : 2025/9/4 22:21
// 邮箱     : 2878548868@qq.com
// 摘要     : 
//////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CONTAINER_TESTMULTISET_H
#define CONTAINER_TESTMULTISET_H
#include <iostream>
#include <set>
#include <vector>

class TestMultiSet
{
public:
    /**
     * @brief 构造函数
     */
    static void Constuctor()
    { // 与set几乎一致，但可以重复
        std::multiset<int> nSet1{}; // 默认std::less按升序排序
        std::multiset<int , std::greater<int>> nSet2{}; // 按降序排序

        std::vector<int> nVec{1,2,3,4,4,3,5}; // 重复元素会被保留
        std::multiset<int> nSet3{nVec.begin() , nVec.end()};

        auto nSet4{nSet3}; // 拷贝构造，深拷贝
        auto nSet5{std::move(nSet4)}; // 移动构造函数
        decltype(nSet3) nSet6{1,2,3,4,5,6,6}; // 初始化列表构造
    }

    // 赋值操作和容量几乎与节点容器一致

    /**
     * @brief 容量
     */
    static void Capacity()
    {
        std::multiset<int> nSet{1, 2, 2, 3, 4, 4, 4};
        std::cout << "Size: " << nSet.size() << std::endl; // 输出: Size: 7
        std::cout << "Empty: " << (nSet.empty() ? "Yes" : "No") << std::endl; // 输出: Empty: No
        std::cout << "Max Size: " << nSet.max_size() << std::endl; // 输出: Max Size: ...
    }

    /**
     * @brief 元素访问
     */
    static void Interview()
    {
        std::multiset<int> nSet{1, 2, 2, 3, 4, 4, 4};
        // 不支持【】运算符、at没有键值对的概念

        auto it = nSet.find(2);
        if (it != nSet.end())
        {
            std::cout << "Element found:" << *it << std::endl;
        }

        if (!nSet.empty())
        {
            std::cout << "First element:" << nSet.begin() << std::endl; // 第一位元素
            std::cout << "Last element:" <<  nSet.rbegin() << std::endl; // 最后一个元素
        }
    }

    /**
     * @brief 增加
     */
    static void Add()
    {
        std::multiset<int> nSet1{};

        auto it = nSet1.insert(1); // 插入单个元素
        nSet1.insert({1,2,3,4,5,1}); // 插入多个元素

        nSet1.emplace(4); // 内部构造插入
        nSet1.emplace_hint(nSet1.end() , 6); // 指定位置插入
    }

    /**
     * @brief 删除
     */
    static void Delete()
    {
        std::multiset<int> nSet{1,2,3,3,4,5,1,3,5,1,2,3};

        auto nCount = nSet.erase(3); // 删除所有值为3的元素

        // 通过迭代器删除
        auto it = nSet.find(2);
        if (it != nSet.end())
        {
            nSet.erase(it);
        }

        // 删除一个范围内的元素
        auto first = nSet.find(4);
        auto last = nSet.end();

        nSet.erase(first , last); // 删除范围内从4开始的所有元素
        nSet.clear(); // 删除所有元素
    }

    static void Modifaction()
    { // 和之前的容器一样为const都不支持直接修改
        std::multiset<int> nSet{1,2,3,3,4,5,1,3,5,1,2,3};
        // 正确的修改方式先删除再添加

        auto range = nSet.equal_range(2);
        for (auto it = range.first ; it != range.second ;)
        {
            it = nSet.erase(it); // 删除当前元素并获取下一个元素的迭代器
            nSet.insert(20); // 插入新值
        }

#ifdef __cpp_lib_node_extract
        auto node = nSet.extract(3);
        if (node.empty())
        {
            node.value() = 30; // 修改提取出来的节点值
            nSet.insert(std::move(node));
        }
#endif
    }

    /**
     * @brief 查找
     */
    static void find()
    {
        std::multiset<int> nSet1 = {1, 2, 2, 3, 3, 3, 4, 5, 5};

        // 使用find()查找元素（返回第一个匹配的元素的迭代器）
        auto it = nSet1.find(3);
        if (it != nSet1.end())
        {
            std::cout << "Found: " << *it << std::endl;
        }

        // 使用count()检查元素出现的次数
        size_t count = nSet1.count(2);
        std::cout << "Element 2 appears " << count << " times." << std::endl;

        // 使用lower_bound()和upper_bound()进行范围查找
        // 查找所有大于等于2且小于4的元素
        auto low = nSet1.lower_bound(2);
        auto up = nSet1.upper_bound(4);
        for (auto it = low; it != up; ++it)
        {
            std::cout << *it << " ";
        }
        std::cout << std::endl;

        // 使用equal_range()获取匹配元素的范围（返回一个pair<iterator, iterator>）
        auto range = nSet1.equal_range(3);
        for (auto it = range.first; it != range.second; ++it)
        {
            std::cout << *it << " "; // 输出所有3
        }
        std::cout << std::endl;
    }
};
#endif //CONTAINER_TESTMULTISET_H